package errors

import (
	"errors"
	"fmt"
)

type ErrorType error

var (
	ErrInternalError        ErrorType = errors.New("internal error")
	ErrInvalidArgs          ErrorType = errors.New("invalid arguments")
	ErrMethodNotImplemented ErrorType = errors.New("method is not implemented")
	ErrNotFound             ErrorType = errors.New("record not found")
	ErrNoAccess             ErrorType = errors.New("no access")
	ErrConflict             ErrorType = errors.New("record already exist")
	ErrInsufficientFunds    ErrorType = errors.New("insufficient funds")
)

type Error interface {
	Error() string
	Type() ErrorType
	Wrap(message string) Error
	SetType(errorType ErrorType) Error
}

type customError struct {
	errorType ErrorType
	err       error
}

func NewWithError(err error, errorType ErrorType) Error {
	return &customError{
		errorType: errorType,
		err:       err,
	}
}

func NewWithMessage(message string, errorType ErrorType) Error {
	return &customError{
		errorType: errorType,
		err:       errors.New(message),
	}
}

func (receiver *customError) Error() string {
	return receiver.err.Error()
}

func (receiver *customError) Type() ErrorType {
	return receiver.errorType
}

func (receiver *customError) Wrap(message string) Error {
	receiver.err = fmt.Errorf("%s: %w", message, receiver.err)

	return receiver
}

func (receiver *customError) SetType(errorType ErrorType) Error {
	receiver.errorType = errorType

	return receiver
}
